#include "optimize.h"

bool copy_merge(MAP x,MAP y){
    if(!map_find(x,0)) {map_cpy(y,x);return true;}
    bool ret=false;
    list nxt=NULL;
    FOR_MAP_2(iter,x,nxt){
        nxt=iter->nxt;
        uLL key=MAP_KEY(iter);
        if(!key) continue;
        void * val=MAP_VAL(iter,void *);
        void ** temp=map_find(y,key);
        if(!temp||*temp!=val){
            ret=true;
            map_erase(x,key);
        }
    }
    return ret;
}

void copy_statement(MAP self,operation * o){
    int op=o->op;
    Operand x=o->x,y=o->y;
    void * ptr=NULL;
    if(op==OP_ASSIGN&&x.var.addr_status==0&&y.var.addr_status==0){
        if(var_mark[x.var.no]||var_mark[y.var.no]) return;
        void ** temp=map_find(self,y.var.no);
        ptr=(void *)((uLL)y.var.no);
        if(temp) ptr=*temp;
        *map_insert(self,x.var.no)=ptr;
    }        
    if(op>=OP_CALL&&op<=OP_DIV){
        list nxt=NULL;
        FOR_MAP_2(iter,self,nxt){
            nxt=iter->nxt;
            if(MAP_KEY(iter)==0) continue;
            if((MAP_KEY(iter)==x.var.no&&MAP_VAL(iter,void *)!=ptr)||MAP_VAL(iter,uLL)==x.var.no) 
                map_erase(self,MAP_KEY(iter));
        }
    }
}

static void swap_cp(MAP self, Operand * x){
    if(x->var.addr_status==CONSTANT_ID||x->var.addr_status<0) return;
    if(var_mark[x->var.no]) return;
    void ** temp=map_find(self,x->var.no);
    if(!temp) return;
    x->var.no=(uLL)*temp;
}

bool copy_optimize(MAP self,operation * o){
    int op=o->op;
    if(op>=OP_ADD&&op<=OP_DIV) swap_cp(self,&o->z);
    if((op>=OP_ASSIGN&&op<=OP_DIV)||op==OP_IF) swap_cp(self,&o->y);
    if(op>=OP_RET&&op<=OP_IF) swap_cp(self,&o->x);
    return true;
}

MAP copy_boundary_init(){
    MAP ret=new_map();
    map_insert(ret,0);
    return ret;
}